package edu.xhu.mycat.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.xhu.api.id.IdClient;
import edu.xhu.mycat.mapper.BiliUserConfigMapper;
import edu.xhu.mycat.mapper.BiliUserInfoMapper;
import edu.xhu.mycat.mapper.BiliUserMapper;
import edu.xhu.mycat.service.BiliUserService;
import edu.xhu.model.biliuser.dtos.LoginAndRegisterDto;
import edu.xhu.model.biliuser.enums.ExperienceEnum;
import edu.xhu.model.biliuser.enums.LevelEnum;
import edu.xhu.model.biliuser.pojos.BiliUser;
import edu.xhu.model.biliuser.pojos.BiliUserConfig;
import edu.xhu.model.biliuser.pojos.BiliUserInfo;
import edu.xhu.model.common.dtos.ResponseResult;
import edu.xhu.model.common.enums.AppHttpCodeEnum;
import edu.xhu.utils.common.AppJwtUtil;
import edu.xhu.utils.common.SaltGenerator;
import edu.xhu.utils.validator.CodeValidator;
import edu.xhu.utils.validator.PhoneValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service
@RequiredArgsConstructor
@Slf4j
public class BiliUserServiceImpl extends ServiceImpl<BiliUserMapper, BiliUser> implements BiliUserService {

    @Resource
    private IdClient idClient;

    private final BiliUserConfigMapper biliUserConfigMapper;

    private final BiliUserInfoMapper biliUserInfoMapper;

    /**
     * 网页端登录功能:手机号,账号登录两种方式
     */
    @Override
    public ResponseResult<?> login(LoginAndRegisterDto dto) {

        //1.1 根据手机号和账号查询用户信息
        BiliUser biliUser = getOne(Wrappers.<BiliUser>lambdaQuery().eq(BiliUser::getPhone, dto.getAccount()));
        if (biliUser == null) {
            //如果手机号不是,采用账号方式登录
            biliUser = getOne(Wrappers.<BiliUser>lambdaQuery().eq(BiliUser::getUserName, dto.getAccount()));
            if (biliUser == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户信息不存在");
            }
        }
        //1.2 比对密码
        String salt = biliUser.getSalt();
        String password = dto.getPassword();
        String pswd = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        if (!pswd.equals(biliUser.getPassword())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        //1.3 返回数据  jwt  user
        String token = AppJwtUtil.getToken(biliUser.getUserId());
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        biliUser.setSalt("");
        biliUser.setPassword("");
        map.put("biliuser", biliUser);

        return ResponseResult.okResult(map);

    }

    /**
     * 网页端注册功能:绑定用手机号注册,注册默认生成账号,默认用账号名为昵称
     * 一定要加事务,进行回滚
     * 注册逻辑:
     * 1.校验格式
     * 2.暂无短信逻辑,这里默认生成密码,随机盐加密
     * 3.生成一个bili全局唯一账户号,同时用户的nickName也是该账户号
     * 4.处理用户三张基本表:bili-user,bili-user-info,bili-user-config
     */
    @Override
    @Transactional
    public ResponseResult<?> register(LoginAndRegisterDto dto) {
        //校验手机号格式
        if (!PhoneValidator.validate(dto.getAccount())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_PATTERN_ERROR, "手机号格式不正确！");
        }
        //校验是否注册过
        BiliUser biliUser = getOne(Wrappers.<BiliUser>lambdaQuery().eq(BiliUser::getPhone, dto.getAccount()));
        if (biliUser != null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "该手机号已被注册！");
        }
        //开始注册逻辑-先判断状态码
        ResponseResult<?> snowflakeDistributedId = idClient.getSnowflakeDistributedId();
        if (!CodeValidator.idValidator(snowflakeDistributedId)) {
            return ResponseResult.errorResult(snowflakeDistributedId.getCode(), "获取id失败！");
        }
        //获取分布式id和随机盐
        Long id = (Long) snowflakeDistributedId.getData();
        String salt = SaltGenerator.generateSalt();
        //构建数据-插入数据,bili-user
        if (
                !save(new BiliUser(id
                        , salt
                        , DigestUtils.md5DigestAsHex((dto.getPassword() + salt).getBytes())
                        , "bili_" + IdUtil.simpleUUID()
                        , dto.getAccount()
                        , new Date()
                        , new Date()
                        , new Date()
                        , "ip", "ip"))) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "保存用户失败！");
        }
        //插入,bili-user-config
        if (biliUserConfigMapper.insert(new BiliUserConfig(id
                , "1"
                , "1"
                ,"1"
                , new Date()
                , null)) < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "保存用户配置失败！");
        }
        //插入,bili-user-info
        if (biliUserInfoMapper.insert(new BiliUserInfo(id
                , "bili_" + PhoneValidator.maskPhoneNumber(dto.getAccount())
                , "默认头像地址"
                , LevelEnum.LEVEL_ZERO.getLevel()
                , ExperienceEnum.LOGIN.getExperience()
                , new Date())) < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "保存用户信息失败！");
        }
        return ResponseResult.okResult("注册成功");
    }

}
